package com.itqf.controller;

import com.google.gson.Gson;
import com.itqf.annotation.JSONType;
import com.itqf.utils.Constants;
import com.itqf.vo.R;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.lang.reflect.Method;

/**
 * projectName: gpshop
 *
 * @author: 赵伟风
 * time: 2021/7/19 17:16
 * description:提取通用的service反射判断方法!供所有controller继承
 */
public class BaseServlet extends HttpServlet {

    @Override
    protected void service(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {

        //1.获取路径并截取调用标识
        //http://localhost:8080/shop/user/login
        //URI: 端口号之后和参数之前
        //URL: 参数之前
        //QueryString: 参数
        String requestURI = req.getRequestURI();

        String methodName = requestURI.substring(requestURI.lastIndexOf(Constants.INDEX) + 1);
        System.out.println("methodName = " + methodName);
        //2.判断进行调用

        /**
         * 反射+泛型+注解
         *
         * 反射:
         *     根据类的class对象,动态的获取类的相关`属性`[属性,方法,构造器,对象实例]
         *     而且打破封装和修饰符的限制!
         *     反射属于软调用,性能偏低!
         *
         * 反射使用:
         *     1.获取类的模板对象
         *        类.class
         *        对象.getClass()
         *        Class.forName(类的全限定名)
         *     2.获取方法
         *        method = class.getMethod(String MethodName,Class...paramClass);
         *        Object ret = method.invoke(对象,方法参数...)
         *     3.获取构造器
         *     4.获取属性
         */
        Class<?> clazz = this.getClass();
        Method method  = null;
        try {
            method = clazz.getMethod(methodName, HttpServletRequest.class, HttpServletResponse.class);
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
            throw new RuntimeException("方法未找到!");
        }


        try {
            //执行对应的方法
            /**
             * 转发 重定向 返回json String
             * 返回字节 返回void
             */
            Object ret = method.invoke(this, req,resp);

            //获取注解
            // method.getAnnotation();
            //判断是否拥有注解
            boolean annotationPresent = method.isAnnotationPresent(JSONType.class);

            if (annotationPresent) {
                resp.setContentType("application/json;charset=utf-8");
            }

            if (ret != null) {
                //不等于空

                if (ret instanceof String)
                {
                    //如果是字符串.转发或者重定向
                    String data = (String) ret;
                    if (data.contains(Constants.FORWARD_ACTION)) {
                        String path = data.substring(Constants.FORWARD_INDEX);
                        req.getRequestDispatcher(path).forward(req,resp);
                    }else if (data.contains(Constants.REDIRECT_ACTION)){
                        String path = data.substring(Constants.REDIRECT_INDEX);
                        resp.sendRedirect(path);
                    }
                }else{
                    //json处理
                    R r = (R) ret;
                    Gson gson = new Gson();
                    String json = gson.toJson(r);
                    resp.getWriter().print(json);
                }
            }

        } catch (Exception e) {
            e.printStackTrace();
            dealError(req,resp);
        }

    }


    public  String dealError(HttpServletRequest request,HttpServletResponse response){
        System.out.println("我们的程序出现异常了！");
        System.out.println("发一个短信或者发一个邮件！");
        //程序员的流程  抛【不要生吞】 收【将所有异常统计收集处理 AOP】 日志 【记录异常发生的位置时间和原因，写清日志】
        //通知【邮件或者短信的形式通知程序员，进行异常处理！】
        //用户错误引导 你的网络异常，你的手机破 ，你的电脑破！稍后再试！
        return "forward:/error/500.jsp";
    }


}
